package com.example.todolist.viewmodel

import android.app.Application
import android.content.Context
import android.util.Log
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.todolist.commen.TodoCategoryEnum
import com.example.todolist.commen.TodoStatus
import com.example.todolist.database.Mydatabase
import com.example.todolist.repository.TodoRepository
import com.example.todolist.database.model.TodoEntity
import com.example.todolist.entity.TodoCategory
import com.example.todolist.entity.TodoOrder
import com.example.todolist.util.AlarmUtils
import com.example.todolist.util.LoggerTag.Companion.MAIN_NOTI
import com.example.todolist.util.LoggerTag.Companion.MAIN_TAG
import com.example.todolist.util.TimeUtils
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject

@HiltViewModel
class TodoListViewModel @Inject constructor(
    @ApplicationContext val context: Context,
    private val repository: TodoRepository
) :
    ViewModel() {
    private val _todoList = MutableLiveData<List<TodoCategory>>()
    val todoList: LiveData<List<TodoCategory>> = _todoList

    init {
//        val todoDao = Mydatabase.getInstance(context)?.getTodoDao()
//        repository = TodoRepository(todoDao)

        viewModelScope.launch {
            // 从 IO 线程获取数据
            val categories = withContext(Dispatchers.IO) { repository.getTodoCategoryList() }
            // 在主线程更新 LiveData
            _todoList.value = categories
        }
    }

    suspend fun insertTodo(todo: TodoEntity) {
//        viewModelScope.launch {
        val id = withContext(Dispatchers.IO) {
            repository.insert(todo)
        }
        todo.id = id.toInt()
        setAlarm(todo)
//        }
    }

    suspend fun getAllTodoCategory(): List<TodoCategory> {
        return withContext(Dispatchers.IO) {
            repository.getTodoCategoryList()
        }
    }


    suspend fun onItemMoved(fromPos: Int, toPos: Int) {
        Log.d(MAIN_TAG, "onItemMoved:$fromPos===>$toPos ")
        Log.d(MAIN_TAG, "onItemMoved:${_todoList.value} ")
        withContext(Dispatchers.IO) {
            val curlist = _todoList.value
            val startId = curlist?.get(fromPos)?.todoId ?: 0
            val endId = curlist?.get(toPos)?.todoId ?: 0
            val startOrder = curlist?.get(fromPos)?.orderNum ?: 0
            val endOrder = curlist?.get(toPos)?.orderNum ?: 0
            val allList = getAllTodoCategory()
            val updateList = ArrayList<TodoOrder>()
//            Log.d(MAIN_TAG, "onItemMoved: ${list?.get(fromPos)},${list?.get(toPos)}")
            if (startOrder > endOrder) {
                // 从上往下扒拉
//                repository.upDrag(startOrder, endOrder)
                for (item in allList) {
                    val orderItem: TodoOrder? = when {
                        item.orderNum in endOrder until startOrder -> TodoOrder().apply {
                            todoId = item.todoId
                            orderNum = item.orderNum + 1
                        }

                        item.todoId == startId -> TodoOrder().apply {
                            todoId = item.todoId
                            orderNum = endOrder
                        }

                        else -> null
                    }
                    orderItem?.let {
                        updateList.add(orderItem)
                    }
                }
            } else if (startOrder < endOrder) {
                // 从下往上扒拉
//                repository.downDrag(startOrder, endOrder)
                for (item in allList) {
                    val orderItem: TodoOrder? = when {
                        item.orderNum in startOrder + 1..endOrder -> TodoOrder().apply {
                            todoId = item.todoId
                            orderNum = item.orderNum - 1
                        }

                        item.todoId == startId -> TodoOrder().apply {
                            todoId = item.todoId
                            orderNum = endOrder
                        }

                        else -> null
                    }
                    orderItem?.let {
                        Log.d(MAIN_TAG, "更新item: ==》前$item 后$orderItem")
                        updateList.add(orderItem)
                    }
                }
            }
            Log.d(MAIN_TAG, "更新列表: ==》$updateList")
            repository.updateOrders(updateList)
        }
    }

    suspend fun getMaxOrder(): Int {
        return withContext(Dispatchers.IO) {
            repository.getMaxOrder()
        }
    }

    suspend fun getTodoById(id: Int): TodoEntity {
        return withContext(Dispatchers.IO) {
            repository.getTodoById(id)
        }
    }

    // 分类搜索
    suspend fun getTodosByCateId(cId: Int) {
        if (cId == TodoCategoryEnum.CATEGORY_ALL.code) {
            val categories = getAllTodoCategory()
            _todoList.value = categories
            Log.d(MAIN_TAG, "getTodosByCateId:${categories} ")
        } else {
            val categories = withContext(Dispatchers.IO) {
                repository.getTodosByCateId(cId)
            }
            _todoList.value = categories
            Log.d(MAIN_TAG, "getTodosByCateId:${categories} ")
        }
    }

    suspend fun updateTodo(todo: TodoEntity) {
        withContext(Dispatchers.IO) { repository.updateTodo(todo) }
        setAlarm(todo)
    }

    suspend fun changeFinishTodo(todoId: Int, isFinish: Boolean) {
//        viewModelScope.launch {
        withContext(Dispatchers.IO) { repository.updateTodoFinish(todoId, isFinish) }
//        }
    }

    suspend fun getAllToDoCnt() = withContext(Dispatchers.IO) {
        repository.getAllToDoCnt()
    }

    suspend fun getFinishToDoCnt() = withContext(Dispatchers.IO) {
        repository.getFinishToDoCnt()
    }


    private fun setAlarm(todo: TodoEntity) {
        if (!todo.isExpired) {
            // 没过期就发送提醒弹窗
            val timeInMills = TimeUtils.timeFormantTimeMills(todo.endTime)
            AlarmUtils.setExactAlarm(
                context, timeInMills, todo
            )
        }
    }

    suspend fun deleteTodos(todos: List<TodoEntity>) {
        withContext(Dispatchers.IO) { repository.delete(*todos.toTypedArray()) }
    }

    fun initIsSelected() {
        val list = _todoList.value?.toMutableList() ?: mutableListOf()
        list.map { it.isSelected = false }
        _todoList.value = list
    }

    suspend fun getListByStatus(status: Int, categoryId: Int) {
        getTodosByCateId(categoryId)
        val curList = _todoList.value ?: emptyList()
        val list: List<TodoCategory>? = when (status) {
            TodoStatus.UPFINISHED.code -> curList.filter { !it.isFinish }

            TodoStatus.FINISHED.code -> curList.filter { it.isFinish }

            TodoStatus.EXPIRED.code -> curList.filter { it.isExpired }

            else -> curList
        }
        _todoList.value = list
    }

    suspend fun updateIsExpired(todoId: Int, isExpired: Boolean) {
        withContext(Dispatchers.IO) {
            repository.updateIsExpired(todoId, isExpired)
            Log.d(MAIN_NOTI, "updateIsExpired:---->---->todo:$todoId")
        }
    }

    fun initTodosExpired() {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                repository.initTodoExpired()
            }
        }
    }
}